//
//  WmcHomeControlView.swift
//  YPWatermarkCamera
//
//  Created by 赵新 on 2022/3/4.
//

import UIKit
import SnapKit
import YPBedrock
import YPGraphicEngine
import RxRelay

// MARK: - [WmcHomeControlView.Config]

extension WmcHomeControlView {
    struct Config {
        static var defaultConfig: Config {
            return .init()
        }

        /// 对焦视图大小
        var focusViewSize: CGSize = 68.wmc_autoHor.yp.cgSize
        /// 对焦视图X秒后透明
        var focusViewAlphaDuration: CGFloat = 1.5
        /// 对焦视图X秒后消失
        var focusViewDismissDuration: CGFloat = 3
        /// 对焦框动画时间
        var focusViewAnimationDuration: CGFloat = Wmc_animationDuration
        /// 曝光条动画时间
        var exposureViewAnimationDuration: CGFloat = Wmc_animationDuration
        /// 最大缩放值
        var maxZoomScale: CGFloat = 10
        /// 缩放视图X秒后消失
        var scaleViewDuration: CGFloat = 2
    }
}

// MARK: - WmcHomeControlView + WmcLifeCycleProtocol

extension WmcHomeControlView: WmcLifeCycleProtocol {
    /// 视图即将出现
    func viewWillAppear(_ vc: WmcBaseVC) {
        guard let _ = vc as? WmcHomeVC else { return }
        loadAssistLineType()
    }
}

// MARK: - [WmcHomeControlView]

class WmcHomeControlView: WmcBaseView {
    // Lifecycle

    convenience init(config: Config) {
        self.init()
        _config = config
    }

    internal required convenience init() {
        self.init(frame: .zero)
        backgroundColor = .clear
        WmcNotice.Register(WmcLifeCycleProtocol.self, observer: self)
    }

    // Internal

    /// 相机视图
    weak var cameraView: YPGECameraView?

    /// 触发的回调
    var hitTestBlock: YPBlock.Empty?

    /// 需要忽略点击事件的区域
    var ignoreViews: [UIView] = []
    /// 需要忽略点击事件的区域2
    var ignoreViews2: [UIView] = []

    /// 是否忽略水印视图的事件透传
    var isIgnoreWatermarkFrames: Bool = false

    /// 配置
    var _config: Config = .defaultConfig

    /// 辅助线视图
    lazy var assistLineLayer: WmcHomeControlAssistLineLayer = {
        let layer = WmcHomeControlAssistLineLayer()
        layer.fillColor = UIColor.clear.cgColor
        layer.strokeColor = UIColor.white.yp.alpha(0.6).cgColor
        return layer
    }()

    /// 对焦视图
    lazy var focusView: WmcHomeControlFocusView = {
        let frame = CGRect(origin: .zero,
                           size: _config.focusViewSize)
        let view = WmcHomeControlFocusView(frame: frame)
        view.yp.makeAnimation { make in
            make.basicAnimation(.transform_scale) { [weak self] make in
                guard let weakSelf = self else { return }
                make.set(duration: weakSelf._config.focusViewAnimationDuration)
                    .set(fromValue: 1)
                    .set(toValue: 0.9)
                    .set(autoreverses: true)
                    .set(removedOnCompletion: false)
                    .setRepeat()
            }
        }
        setShadow(view)
        return view
    }()

    /// 曝光条
    lazy var exposureView: WmcHomeControlExposureView = {
        let view = WmcHomeControlExposureView(frame: .zero)
        view.yp.makeAnimation { make in
            //            make.basicAnimation(.opacity) { [weak self] make in
            //                guard let weakSelf = self else { return }
            //                make.set(duration:weakSelf._config.exposureViewAnimationDuration)
            //                    .set(fromValue:1)
            //                    .set(toValue:0.5)
            //                    .set(autoreverses:true)
            //                    .set(removedOnCompletion:false)
            //                    .setRepeat()
            //            }
        }
        view.biseBlock = { [weak self] bise in
            guard let weakSelf = self else { return }
            WmcLogManager.Log("当前曝光值：\(bise)")
            weakSelf.cameraView?.setExposure(bise)
            //            weakSelf.cameraView?.setExposure(bise, tapPoint: weakSelf.tapGestureStartPoint)

            // 当曝光量过高
            //            if bise / weakSelf.exposureView.maxBias > 0.4 {
            //                weakSelf.setIndicatorColor(.wmc_mainTheme)
            //            } else {
            //                weakSelf.setIndicatorColor(.white)
            //            }
        }
        setShadow(view)
        return view
    }()

    /// 缩放值Label
    lazy var scaleNumLabel: UILabel = {
        let label = UILabel.YP.Create(font: 50.yp.uiFont(weight: .medium),
                                      color: UIColor.white,
                                      alignment: .center)
        label.isHidden = true
        setShadow(label)
        return label
    }()
   
    /// 点击对焦手势
    lazy var tapGesture: UITapGestureRecognizer = {
        let gesture = UITapGestureRecognizer.YP.Create { [weak self] tap in
            guard let weakSelf = self else { return }
            // 声明开始操作
            weakSelf.startFocusAction()

            // 震动
            YPDevice.PlayShake(.medium)

            // 视图内点击坐标
            let tapPoint = tap.location(in: tap.view)

            // 保存点击坐标
            weakSelf.tapGestureStartPoint = tapPoint

            // 做对焦视图动画
            let focusView = weakSelf.focusView
            focusView.center = tapPoint
            // 相机进行对焦
            weakSelf.cameraView?.setFoucsPoint(tapPoint)

            // 曝光视图位置调整
            let exposureView = weakSelf.exposureView
            exposureView.snp.remakeConstraints { make in
                make.top.equalTo(focusView).offset(-20)
                make.bottom.equalTo(focusView).offset(20)
                make.width.equalTo(25)
                if tapPoint.x >= (Wmc_screenWidth / 2.0) { // 右半边
                    make.right.equalTo(focusView.snp_leftMargin).offset(-20)
                } else {
                    make.left.equalTo(focusView.snp_rightMargin).offset(20)
                }
            }
            // 先重置曝光指示器颜色
            exposureView.clearRecord()
            weakSelf.cameraView?.setExposure(0)
            // 开启曝光操作
            weakSelf.addGestureRecognizer(weakSelf.panGesture)
        }
        return gesture
    }()

    /// 曝光拖拽
    lazy var panGesture: UIPanGestureRecognizer = {
        let gesture = UIPanGestureRecognizer.YP.Create { [weak self] pan in
            guard let weakSelf = self else { return }
            // 声明开始操作
            weakSelf.startFocusAction()

            // 视图内拖拽坐标
            let panPoint = pan.location(in: pan.view)
            switch pan.state {
            case .began: // 开始拖拽，记录起始坐标
                weakSelf.panGestureStartPoint = panPoint
                YPDevice.PlayShake(.medium)
            case .changed: // 拖拽中，计算相对坐标
                guard let startPointY = weakSelf.panGestureStartPoint?.y else { return }
                let panY = panPoint.y
                let changeY = panY - startPointY
                weakSelf.exposureView.setSliderCenter(changeY)
            case .ended:
                weakSelf.exposureView.updateOffsetCenterY()
                YPDevice.PlayShake(.heavy)
            default: break
            }
        }
        return gesture
    }()

    /// 捏合缩放手势
    lazy var pinchGesture: UIPinchGestureRecognizer = {
        let gesture = UIPinchGestureRecognizer.YP.Create { [weak self] pinch in
            guard let weakSelf = self else { return }
            switch pinch.state {
            case .began: // 开始拖拽，记录起始缩放值
                weakSelf.beforeZoomFactor = weakSelf.cameraView?.zoomFactor()
                weakSelf.willChangeFocus.accept(())
            case .changed: // 缩放中，计算相对坐标
                guard let beforeZoomFactor = weakSelf.beforeZoomFactor else { return }
                let scale = min(beforeZoomFactor * pinch.scale, weakSelf._config.maxZoomScale)
                weakSelf.setCameraZoomFactor(scale: scale)
                // 回调
                weakSelf.focusZoomScaleChanged.accept(scale)
            case .ended:
                weakSelf.beforeZoomFactor = nil
                weakSelf.didEndChangeFocus.accept(())
            default: break
            }
        }
        return gesture
    }()

    /// 延时倒计时显示Label
    lazy var delayLabel: UILabel = {
        let label = UILabel.YP.Create(font: 100.yp.uiFont(weight: .medium),
                                      color: UIColor.white,
                                      alignment: .center)
        label.isHidden = true
        setShadow(label)
        return label
    }()

    /// 虚线框
    lazy var dottedLayer: CAShapeLayer = {
        let layer = CAShapeLayer()
        layer.fillColor = UIColor.clear.cgColor
        layer.strokeColor = UIColor.white.cgColor
        layer.lineWidth = 2
        layer.lineJoin = .round
        layer.lineDashPattern = [NSNumber(value: 5), NSNumber(value: 3)]
        layer.isHidden = true
        layer.shadowColor = UIColor.wmc_grayH5_606066.cgColor
        layer.shadowRadius = 4
        layer.shadowOffset = CGSize(width: 0, height: 1)
        layer.shadowOpacity = 0.8
        layer.yp.makeAnimation { make in
            make.basicAnimation(.opacity) { make in
                make.set(duration: Wmc_animationDuration)
                    .set(fromValue: 1)
                    .set(toValue: 0)
                    .set(autoreverses: true)
                    .set(removedOnCompletion: false)
                    .setRepeat()
            }
        }
        return layer
    }()

    /// AI标识
    lazy var aiLogoView: WmcHomeControlAILogoView = {
        let view = WmcHomeControlAILogoView()
        view.isHidden = true
        return view
    }()

    /// 倒计时计时器
    var delayTimer: Timer?

    var delayTime: Int = 0

    var tipsViews: [String: UIView] = [:]
    
    
    /// 焦距倍数变化回调
    let focusZoomScaleChanged: PublishRelay<CGFloat> = .init()
    /// 将要开始缩放改变焦距
    let willChangeFocus: PublishRelay<Void> = .init()
    /// 已经结束焦距改变
    let didEndChangeFocus: PublishRelay<Void> = .init()
    

    /// 加载辅助线样式
    func loadAssistLineType() {
        let commonSettings = WmcPreferenceSettingsManager.shared.cameraSetting
        let rawValue = commonSettings.assistLineStyle
        let cas = WmcHomeControlAssistLineLayer.AssistLineStyle(rawValue: rawValue) ?? .none
        assistLineLayer.assistLineType = cas
    }
    
    
    

    override func layoutSubviews() {
        super.layoutSubviews()
        assistLineLayer.frame = bounds
    }

    /// 重写
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        // 回调事件
        hitTestBlock?()

        if !isIgnoreWatermarkFrames {
            for view in ignoreViews {
                let frame = view.convert(view.bounds, to: self)
                if frame.contains(point) {
                    return nil
                }
            }
        }
        for view in ignoreViews2 {
            let frame = view.convert(view.bounds, to: self)
            if frame.contains(point) {
                return nil
            }
        }
        return super.hitTest(point, with: event)
    }

    /// 设置倒计时
    func setDelayTakePhotoAnimation(_ time: Int) {
        guard time != 0 else { return }
        delayTime = time
        cancelDelayTakePhotoAnimation()
        delayTimerAnimation()
        delayTimer = .scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(self.delayTimerAnimation),
                                     userInfo: nil,
                                     repeats: true)
    }

    func cancelDelayTakePhotoAnimation() {
        delayTimer?.invalidate()
        delayTimer = nil
    }

    @objc
    func delayTimerAnimation() {
        delayLabel.text = delayTime.yp.string
        // 震动反馈
        YPDevice.PlayShake(.light)
        // 动画
        delayLabel.isHidden = false
        delayLabel.transform = .YP.CreateScale(2)
        UIView.animate(withDuration: 0.95,
                       delay: 0,
                       usingSpringWithDamping: 0.5,
                       initialSpringVelocity: 1,
                       options: .curveEaseInOut) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.delayLabel.transform = .YP.CreateScale(1)
        } completion: { [weak self] _ in
            guard let weakSelf = self else { return }
            weakSelf.delayLabel.isHidden = true
        }
        if delayTime <= 0 { // 计时结束
            // 震动反馈
            YPDevice.PlayShake(.threeShort)
            // 隐藏
            delayLabel.isHidden = true
            // 取消计时器
            cancelDelayTakePhotoAnimation()
            delayTime = 0
        }
        delayTime -= 1
    }

    /// 水印移动时
    func watermarkMove(_ watermarkView: WmcBaseWatermarkTemplateView) {
        updateDottedLayer(watermarkView: watermarkView)
    }

    // MARK: UI
    override func makeUI() {
        layer.addSublayer(assistLineLayer)

        addSubview(delayLabel)
        addSubview(focusView)
        addGestureRecognizer(tapGesture)
        addGestureRecognizer(pinchGesture)

        addSubview(exposureView)
        addSubview(scaleNumLabel)
        addSubview(aiLogoView)

        delayLabel.snp.makeConstraints { make in
            make.left.right.centerY.equalToSuperview()
        }

        scaleNumLabel.snp.makeConstraints { make in
            let navHeight = Wmc_statusBarHeight + 50
            make.top.equalTo(navHeight + 30)
            make.left.right.equalToSuperview()
            make.height.equalTo(60)
        }

        aiLogoView.snp.makeConstraints { make in
            make.left.equalTo(Wmc_standardEdge.left)
            make.bottom.equalTo(-Wmc_standardEdge.bottom)
            make.size.equalTo(CGSize(width: 226, height: 28))
        }
    
    }
    
    // MARK: Bind Action
    
    override func bindViewAction() {
        super.bindViewAction()
        
    }

    /// 添加提示视图
    func addTipsView(key: String, view: UIView) {
        // 先判断Key值重复
        removeTipsView(key: key)
        tipsViews[key] = view
        addSubview(view)
    }

    /// 移除某个视图
    func removeTipsView(key: String) {
        // 先判断Key值重复
        if let view = tipsViews[key] {
            view.removeFromSuperview()
        }
        tipsViews.removeValue(forKey: key)
    }

    /// 移除所有提示视图
    func removeAllTipsViews() {
        let keys = tipsViews.keys
        for key in keys {
            if let view = tipsViews[key] {
                view.removeFromSuperview()
            }
        }
    }

    /// 设置视图阴影
    func setShadow(_ view: UIView, color: UIColor = UIColor.wmc_grayH5_606066) {
        view.layer.shadowColor = color.cgColor
        view.layer.shadowRadius = 4
        view.layer.shadowOffset = CGSize(width: 0, height: 1)
        view.layer.shadowOpacity = 0.8
    }

    /// 虚线闪烁
    func flashDottedLayer() {
        YPGCD.Main { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.dottedLayer.isHidden = false
            weakSelf.dottedLayer.yp.delayLast(2) { [weak self] in
                guard let weakSelf = self else { return }
                weakSelf.stopFlashDottedLayer()
            }
        }
    }

    /// 立刻停止闪烁
    /// 用于拍照时防止虚线拍进去
    func stopFlashDottedLayer() {
        YPGCD.Main { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.dottedLayer.isHidden = true
        }
    }

    /// 更新虚线框
    func updateDottedLayer(watermarkView: WmcBaseWatermarkTemplateView) {
        let watermarkSize = CGSize(width: watermarkView.frame.width + watermarkView.edgeCompensateDistance.yp.horizontal,
                                   height: watermarkView.frame.height + watermarkView.edgeCompensateDistance.yp.vertical)
        let dottedFrame = CGRect(x: -watermarkView.edgeCompensateDistance.left,
                                 y: -watermarkView.edgeCompensateDistance.top,
                                 width: watermarkSize.width, height: watermarkSize.height)
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        dottedLayer.frame = .init(origin: watermarkView.frame.origin, size: watermarkView.frame.size)
        let path = UIBezierPath(roundedRect: dottedFrame, cornerRadius: 8)
        dottedLayer.path = path.cgPath
        CATransaction.commit()
        layer.addSublayer(dottedLayer)
    }

    func setCameraView(_ cameraView: YPGECameraView) {
        self.cameraView = cameraView

        // 同步相机设置数据
        exposureView.maxBias = cameraView.maxExposure() * 0.2
        exposureView.minBias = cameraView.minExposure() * 0.2
    }

    // Private

    /// 拖拽起始坐标
    private var tapGestureStartPoint: CGPoint?
    /// 拖拽起始坐标
    private var panGestureStartPoint: CGPoint?
    /// 上一次缩放
    private var beforeZoomFactor: CGFloat?
    /// 上一次显示的缩放值
    private var beforeScaleString: String = ""

    /// 开始对焦曝光操作
    private func startFocusAction() {
        // 设置视图
        focusView.alpha = 1
        exposureView.alpha = 1
        focusView.isHidden = false
        exposureView.isHidden = false
        // 延时Xs后结束操作
        focusView.yp.delayLast(_config.focusViewAlphaDuration) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.alphaFocusAction()
        }
        // 延时Xs后结束操作
        exposureView.yp.delayLast(_config.focusViewDismissDuration) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.endFocusAction()
        }
    }

    private func alphaFocusAction() {
        focusView.alpha = 0.5
        exposureView.alpha = 0.5
    }

    /// 结束对焦曝光操作
    private func endFocusAction() {
        tapGestureStartPoint = nil
        focusView.isHidden = true
        exposureView.isHidden = true

        // 关闭曝光操作
        removeGestureRecognizer(panGesture)
        // 切换到自动对焦
        yp.delayLast(5) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.cameraView?.setContinuousAutoFocus()
        }
    }

    /// 开始缩放操作
    private func startScaleAction(_ scale: CGFloat) {
        scaleNumLabel.isHidden = false
        let oneFloatScale = String(format: "%.1f", scale).yp.removeSuffix(string: ".0")
        scaleNumLabel.text = "\(oneFloatScale)x"
        // 刻度震动
        var vibrationNumArr: [String] = []
        let maxInt = _config.maxZoomScale.yp.int
        for i in 1 ... maxInt {
            let str = i.yp.string
            vibrationNumArr.append(str)
            let halfStr = "\(str).5"
            if halfStr.yp.float < maxInt.yp.float {
                vibrationNumArr.append(halfStr)
            }
        }
        if vibrationNumArr.contains(oneFloatScale),
           beforeScaleString != oneFloatScale {
            YPDevice.PlayVibration(.light)
        }
        beforeScaleString = oneFloatScale
        // 延时Xs后结束操作
        scaleNumLabel.yp.delayLast(_config.scaleViewDuration) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.endScaleAction()
        }
    }

    /// 结束缩放操作
    private func endScaleAction() {
        scaleNumLabel.isHidden = true
    }
}

extension WmcHomeControlView {
    
    // MARK: Private
    
    
    
    // MARK: Public
    
    /// 设置相机的焦距缩放倍数
    /// - Parameters:
    ///   - scale: 缩放倍数
    ///   - slient: 是否静默(即不显示缩放倍数提示)
    func setCameraZoomFactor(scale: CGFloat, slient: Bool = false) {
        let zoomScale = max(1.0, scale)
        cameraView?.setZoomFactor(zoomScale)
        if !slient {
            startScaleAction(zoomScale)
        }
    }
    
}
